package com.jshcbd.modules.asset.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jshcbd.common.util.ConvertUtils;
import com.jshcbd.common.util.DateUtils;
import com.jshcbd.framework.poi.excel.ExcelExportUtil;
import com.jshcbd.framework.poi.excel.ExcelImportUtil;
import com.jshcbd.framework.poi.excel.def.NormalExcelConstants;
import com.jshcbd.framework.poi.excel.entity.ExportParams;
import com.jshcbd.framework.poi.excel.entity.ImportParams;
import com.jshcbd.framework.poi.excel.entity.result.ExcelImportResult;
import com.jshcbd.framework.poi.excel.html.ExcelToHtmlServer;
import com.jshcbd.framework.poi.excel.imports.ExcelImportServer;
import com.jshcbd.framework.poi.excel.view.EntityExcelView;
import com.jshcbd.framework.vo.Result;
import com.jshcbd.framework.query.QueryGenerator;
import com.jshcbd.framework.vo.LoginUser;

import com.jshcbd.modules.asset.dto.AssetExcelDto;
import com.jshcbd.modules.asset.entity.AssetClassesEntity;
import com.jshcbd.modules.asset.entity.AssetEntity;
import com.jshcbd.modules.asset.service.IAssetService;
import com.jshcbd.modules.asset.service.IClassesService;
import com.jshcbd.modules.asset.vo.AssetVo;
import com.jshcbd.modules.asset.vo.DepreciationVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.POIXMLDocument;
import org.apache.poi.POIXMLDocumentPart;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.ss.usermodel.PictureData;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.*;
import org.apache.shiro.SecurityUtils;
import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTMarker;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * @author zhoucd
 * @date
 * @description
 */
@Slf4j
@Api(tags="资产管理")
@RestController
@RequestMapping("/asset")
public class AssetController {

    @Autowired
    private IAssetService assetService;

    @Autowired
    private IClassesService classesService;



    @Value(value = "${jshcbd.path.upload}")
    private String uploadpath;


    @ApiOperation("根据Id获取资产信息")
    @GetMapping("/getInfo/{id}")
    public AssetEntity queryPageList(@PathVariable String id) {
        return  assetService.getById(id);
    }



    @ApiOperation("资产列表")
    @GetMapping("/list")
    public Result<IPage<AssetVo>> queryPageList(AssetVo assetVo, @RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
                                                @RequestParam(name="pageSize", defaultValue="10") Integer pageSize, HttpServletRequest req) {
        QueryWrapper<AssetVo> queryWrapper = QueryGenerator.initQueryWrapper(assetVo, req.getParameterMap());
        Page<AssetVo> page = new Page(pageNo, pageSize);
        Result<IPage<AssetVo>> result = this.queryPage(page, queryWrapper);
        return result;
    }


    @ApiOperation("资产标签绑定列表")
    @GetMapping("/bindingList/{type}")
    public Result<IPage<AssetVo>> bindingList(AssetVo assetVo,
                                                @PathVariable @ApiParam("1:待绑定，2已绑定") Integer type,
                                                @RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
                                                @RequestParam(name="pageSize", defaultValue="10") Integer pageSize, HttpServletRequest req) {
        QueryWrapper<AssetVo> queryWrapper = QueryGenerator.initQueryWrapper(assetVo, req.getParameterMap());
        if(type == 1){
            queryWrapper.isNull("rfid");
        }else{
            queryWrapper.isNotNull("rfid");
        }
        Page<AssetVo> page = new Page(pageNo, pageSize);
        Result<IPage<AssetVo>> result = this.queryPage(page, queryWrapper);
        return result;
    }



    private Result<IPage<AssetVo>> queryPage(Page<AssetVo> page, QueryWrapper<AssetVo> queryWrapper){
        Result<IPage<AssetVo>> result = new Result();
        IPage<AssetVo> pageList = assetService.pageView(page, queryWrapper);
        result.setData(pageList);
        log.info(pageList.toString());
        return result;
    }




    @ApiOperation("资产折旧")
    @GetMapping("/depreciation")
    public Result<IPage<DepreciationVo>> queryPageList(Integer year, AssetVo assetVo, @RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
                                                       @RequestParam(name="pageSize", defaultValue="10") Integer pageSize, HttpServletRequest req) {

        Result<IPage<DepreciationVo>> result = new Result();
        QueryWrapper<AssetVo> queryWrapper = QueryGenerator.initQueryWrapper(assetVo, req.getParameterMap());
        Page<AssetVo> page = new Page(pageNo, pageSize);
        IPage<AssetVo> pageList = assetService.pageView(page, queryWrapper);
        List<DepreciationVo> dataList = pageList.getRecords().stream().map(vo -> new DepreciationVo(vo).setYear(year)).collect(Collectors.toList());
        Page<DepreciationVo> resultPage = new Page(pageNo, pageSize);
        BeanUtils.copyProperties(pageList,resultPage);
        resultPage.setRecords(dataList);
        result.setData(resultPage);
        return result;
    }




    @ApiOperation("资产折旧")
    @GetMapping("/depreciationExprot")
    public ModelAndView depreciationExprot(Integer year, AssetVo assetVo,
                                           HttpServletRequest req,
                                           HttpServletResponse res) {
        LoginUser user = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        List<DepreciationVo> dataList = this.depreciationList(year, assetVo, req);
        String title = "资产折旧";
        // Step.3 AutoPoi 导出Excel
        ModelAndView mv = new ModelAndView(new EntityExcelView());
        mv.addObject(NormalExcelConstants.FILE_NAME, title); //此处设置的filename无效 ,前端会重更新设置一下
        mv.addObject(NormalExcelConstants.CLASS, DepreciationVo.class);
        mv.addObject(NormalExcelConstants.PARAMS, new ExportParams(year+"-资产折旧表表", title));
        mv.addObject(NormalExcelConstants.DATA_LIST, dataList);
        return mv;
    }



    private  List<DepreciationVo>  depreciationList(Integer year, AssetVo assetVo,HttpServletRequest req){
        QueryWrapper<AssetVo> queryWrapper = QueryGenerator.initQueryWrapper(assetVo, req.getParameterMap());
        List<AssetVo> assetVoList = assetService.listView(queryWrapper);
        List<DepreciationVo> dataList = assetVoList.stream()
                .map(vo -> new DepreciationVo(vo).setYear(year))
                .collect(Collectors.toList());

        return dataList;

    }

    @ApiOperation("资产折旧打印")
    @GetMapping("/print")
    public String print(Integer year, AssetVo assetVo,
                                           HttpServletRequest req,
                                           HttpServletResponse res) {
        LoginUser user = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        List<DepreciationVo> dataList = this.depreciationList(year, assetVo, req);
        Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams( year+"-资产折旧表表", "资产折旧表表"),
                DepreciationVo.class,dataList);
        ExcelToHtmlServer excelToHtmlServer = new ExcelToHtmlServer(workbook,true,0);
        return excelToHtmlServer.printPage();
    }


    @ApiOperation("绑定资产标签RFID")
    @GetMapping("/binding/{id}/{rfid}")
    public Result binding(@PathVariable String id,@PathVariable String rfid,
                        HttpServletRequest req,
                        HttpServletResponse res) {
        AssetEntity entity = assetService.getById(id);

        try {
            if(entity == null){
                return Result.error("资产实体不存在！");
            }
            entity.setRfid(rfid);
            assetService.updateById(entity);
            return Result.ok();
        }catch (Exception e){
            return Result.error("RFID已绑定，不可重复绑定，请检查!");
        }
    }


    /**
     * excel导入
     *
     * @param request
     * @param response
     * @return
     */
    @PostMapping(value = "/importExcel")
    public Result importExcel(HttpServletRequest request, HttpServletResponse response) {
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
        for (Map.Entry<String, MultipartFile> entity : fileMap.entrySet()) {
            MultipartFile file = entity.getValue();// 获取上传文件对象
            ImportParams params = new ImportParams();
            params.setTitleRows(0);
            params.setHeadRows(1);
            try {

                long start = System.currentTimeMillis();
                ExcelImportResult excelImportResult = new ExcelImportServer().importExcelByIs(file.getInputStream(), AssetExcelDto.class, params);
                List<AssetExcelDto> dataList = excelImportResult.getList();

                Sheet sheet = excelImportResult.getWorkbook().getSheetAt(0);
                if (excelImportResult.getWorkbook()  instanceof  HSSFWorkbook) {
                    HSSFSheet hssfSheet =(HSSFSheet)sheet;
                    List<HSSFShape> list = hssfSheet.getDrawingPatriarch().getChildren();
                    for (HSSFShape shape : list) {
                        if (shape instanceof HSSFPicture) {
                            HSSFPicture picture = (HSSFPicture) shape;
                            HSSFClientAnchor cAnchor = (HSSFClientAnchor) picture.getAnchor();
                            PictureData pdata = picture.getPictureData();
                            String key = cAnchor.getRow1() + "-" + cAnchor.getCol1(); // 行号-列号
                            String savePath = this.saveImgLocal(picture.getPictureData(),key);
                            dataList.get(cAnchor.getRow1()-1).setPhoto(savePath);
                        }
                    }
                } else if (excelImportResult.getWorkbook()  instanceof XSSFWorkbook ) {
                    XSSFSheet xssfSheet =  (XSSFSheet) sheet;
                    List<POIXMLDocumentPart> list = xssfSheet.getRelations();
                    for (POIXMLDocumentPart part : list) {
                        if (part instanceof XSSFDrawing) {
                            XSSFDrawing drawing = (XSSFDrawing) part;
                            List<XSSFShape> shapes = drawing.getShapes();
                            for (XSSFShape shape : shapes) {
                                XSSFPicture picture = (XSSFPicture) shape;
                                XSSFClientAnchor anchor = picture.getPreferredSize();
                                CTMarker marker = anchor.getFrom();
                                String key = marker.getRow() + "-" + marker.getCol();
                                String savePath =  this.saveImgLocal(picture.getPictureData(),key);
                                dataList.get(marker.getRow()-1).setPhoto(savePath);
                            }
                        }
                    }
                }

                String date = DateUtils.getDate("yyMMddHHmm");
                AtomicInteger count = new AtomicInteger(1);
                List<AssetEntity> assetList = dataList.stream().map(excelDto -> {
                    AssetEntity assetEntity = new AssetEntity();
                    BeanUtils.copyProperties(excelDto,assetEntity);

                    assetEntity.setNumber(excelDto.getClassesCode()+date
                            + ConvertUtils.generateAssetNumber(count.intValue(),4));
                    //创建领用信息
                    QueryWrapper tempQuery = new QueryWrapper();
                    tempQuery.eq("code",excelDto.getClassesCode());
                    AssetClassesEntity classesEntity = classesService.getOne(tempQuery);
                    //资产分类
                    assetEntity.setClassesId(classesEntity.getId());
                    count.getAndIncrement();
                    return assetEntity;
                }).collect(Collectors.toList());
                assetService.saveBatch(assetList);
                log.info("消耗时间" + (System.currentTimeMillis() - start) + "毫秒");
                //update-end-author:taoyan date:20190528 for:批量插入数据
                return Result.ok("文件导入成功！数据行数：" + dataList.size());
            } catch (Exception e) {
                log.error(e.getMessage(), e);
                return Result.error("文件导入失败:" + e.getMessage());
            } finally {
                try {
                    file.getInputStream().close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return Result.ok();
    }


    /**
     * 本地文件上传
     * @param  文件
     * @param   自定义路径
     * @return
     */
    private String saveImgLocal(PictureData pic, String picName){
        try {
            String fileName = null;
            File file = new File(uploadpath + File.separator  );
            if (!file.exists()) {
                file.mkdirs();// 创建文件根目录
            }

            fileName = picName+ "_" + System.currentTimeMillis() + ".jpg";
            //图片保存路径
            FileOutputStream out = new FileOutputStream(uploadpath + File.separator+fileName);
            out.write(pic.getData());
            out.close();
            return fileName;
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        }
        return "";
    }



}
